package com.hemerasolutions.v2trainer.component.detail;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;

import org.primefaces.event.TransferEvent;
import org.primefaces.model.DualListModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.hemerasolutions.v2trainer.component.BaseComponent;
import com.hemerasolutions.v2trainer.component.interfaces.detail.ModalityDetailsCompInterface;
import com.hemerasolutions.v2trainer.component.interfaces.list.ModalityIZListCompInterface;
import com.hemerasolutions.v2trainer.component.interfaces.table.ExerciseTableCompInterface;
import com.hemerasolutions.v2trainer.delegate.interfaces.ModalityDetailDelegateInterface;
import com.hemerasolutions.v2trainer.model.exercise.Exercise;
import com.hemerasolutions.v2trainer.model.exercise.VersionableExercise;
import com.hemerasolutions.v2trainer.model.exercise.executions.AssociationET;
import com.hemerasolutions.v2trainer.model.exercise.executions.Execution;
import com.hemerasolutions.v2trainer.model.training.TrainingType;
import com.hemerasolutions.v2trainer.model.unit.volume.VolumeType;
import com.hemerasolutions.v2trainer.model.modality.Modality;
import com.hemerasolutions.v2trainer.model.modality.VersionableModality;
import com.hemerasolutions.v2trainer.service.interfaces.ModalityServiceInterface;

@Component("modalityDetailsComp")
@Scope("prototype")
public class ModalityDetailsComp extends BaseComponent implements ModalityDetailsCompInterface {

	private static final long serialVersionUID = 1L;

	private VersionableModality versionableModality;
	
	private Modality modality;
	
	private List<TrainingType> trainingTypes;
	
	private DualListModel<Execution> executions;
	
	private DualListModel<VolumeType> volumes;
	
	private TrainingType newTrainingTypeValue;

	private ModalityDetailDelegateInterface delegate;
	
	@Autowired
	private ExerciseTableCompInterface exerciseTableComp;	 
	
	@Autowired
	private ModalityServiceInterface modalityService;
	
	@Autowired
	private ModalityIZListCompInterface modalityIZList;
	
	@PostConstruct
	@Override
	public void init(){
		super.init();
	}

	@Override
	public void refresh(){

		if(this.versionableModality != null){
			this.trainingTypes = modalityService.listTrainingTypes();
			this.executions = new DualListModel<Execution>();
			this.volumes = new DualListModel<VolumeType>(); 
			this.loadModalityTrainingType();
			
			
			
			this.exerciseTableComp.setModality(this.modality);
			this.exerciseTableComp.refresh();
		}
	} 
	
	

	@Override
	public void saveModality(ActionEvent ev){
		if(this.delegate != null){
			this.delegate.onSaveVersionableModality(this.versionableModality,ev);
		}
	}
	
	@Override
	public void createModality(ActionEvent ev){
		if(this.delegate != null){
			this.delegate.onCreateVersionableModality(this.versionableModality,ev);
		}
	}
	
	
	@Override
	public void onChangeVolume(TransferEvent ev){

		for(Object obj:ev.getItems()){

			VolumeType volType = null;

			volType = (VolumeType)obj;				
			
			if(ev.isRemove()){
				if(this.volumeTypeInUse((VolumeType)volType)){
					this.showInfoMessage(	this.localizedText("Error"),
							this.localizedText("TheVolumeType") + " " +
									this.localizedText(((VolumeType)volType).getName()) + " "+
									this.localizedText("isInUseInOneOrMoreExercises"));							
					this.volumes.getTarget().add((VolumeType)volType);
					this.volumes.getSource().remove((VolumeType)volType);
					
				}else{
					this.modality.getVolumeTypes().remove((VolumeType)volType);
				}
			}else{
				this.modality.getVolumeTypes().add((VolumeType)volType);
			}
		}
		
	}
	
	private boolean volumeTypeInUse(VolumeType volType) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onVersionChanged(ValueChangeEvent e){
		this.refresh();
	}	
	
	@Override
	public void onChangeExecution(TransferEvent ev){

		for(Object obj:ev.getItems()){
			Execution exec = null;
			exec = (Execution)obj;				

			if(ev.isRemove()){
				if(this.executionInUse(exec)){
					this.showInfoMessage(	this.localizedText("Error"),
							this.localizedText("TheExecution") + " " +
									this.localizedText(((Execution)exec).getName()) + " "+
									this.localizedText("isInUseInOneOrMoreExercises"));							
					this.executions.getTarget().add((Execution)exec);
					this.executions.getSource().remove((Execution)exec);
					
				}else{
					this.modality.getExecutions().remove(exec);
				}
			}else{
				this.modality.getExecutions().add(exec);
			}
		}
		
	}
	
	private boolean executionInUse(Execution exec) {
		
		for(VersionableExercise ve:this.modality.getVersionableExercises())
		for(Exercise exercise:ve.getExerciseVersions()){
			for(Execution ex:exercise.getExecutions()){
				if(ex.equals(exec)){
					return true;
				}
			}
		}
		
		return false;
	}

    @Override
	public void onTrainingTypeChange(ValueChangeEvent e){
    	if(!this.modality.getVersionableExercises().isEmpty()){
			this.showErrorMessage(	this.localizedText("Error"),
					this.localizedText("CantChangeTheTypeOfCurrentExercises"));
			this.showInfoMessage(	this.localizedText("Tip"),
					this.localizedText("RemoveTheModalityExercisesBeforeChangeType"));
			this.newTrainingTypeValue = (TrainingType)e.getOldValue();
    	}else{
			this.newTrainingTypeValue = (TrainingType)e.getNewValue();
    	}
    }
    
	@Override
	public void trainingTypeChanged( ){
		this.modality.setTrainingType(this.newTrainingTypeValue);	
		
		if(this.modality.getTrainingType() != null && this.modality.getVersionableExercises().isEmpty()){

			this.executions.setSource(new ArrayList<Execution>());
			this.volumes.setSource(new ArrayList<VolumeType>());
			this.modality.setExecutions(new ArrayList<Execution>());
			this.modality.setVolumeTypes(new ArrayList<VolumeType>());
			this.executions.setTarget(this.modality.getExecutions());
			this.volumes.setTarget(this.modality.getVolumeTypes());
			
			for(AssociationET assoc: this.modality.getTrainingType().getAssociationETs()){
				this.executions.getSource().add(assoc.getExecution());
			}
			
			for(VolumeType volType: this.modality.getTrainingType().getVolumeTypes()){
				this.volumes.getSource().add(volType);
			}
		}
	}

	@Override
	public void loadModalityTrainingType(){

		if(this.modality != null){

			if(this.modality.getTrainingType() == null){
				if(!this.trainingTypes.isEmpty()){
					this.modality.setTrainingType(this.trainingTypes.get(0));
				}else{
					return;
				}
			}			
			
			this.executions.setSource(new ArrayList<Execution>());
			this.volumes.setSource(new ArrayList<VolumeType>());
			this.executions.setTarget(this.modality.getExecutions());
			this.volumes.setTarget(this.modality.getVolumeTypes());
			
			for(AssociationET assoc: this.modality.getTrainingType().getAssociationETs()){
				if(!this.modality.getExecutions().contains(assoc.getExecution())){
					this.executions.getSource().add(assoc.getExecution());
				}
			}
			
			for(VolumeType volType: this.modality.getTrainingType().getVolumeTypes()){
				if(!this.modality.getVolumeTypes().contains(volType)){
					this.volumes.getSource().add(volType);
				}
			}
		}
		
	}
	
	@Override
    public void toIntensityModality(){
		if(this.modality.getExecutions().isEmpty()){
			this.showErrorMessage(	this.localizedText("Error"),
									this.localizedText("NoExecutionSelected"));
			return ;
		}

		this.modalityIZList.setModality(this.modality);
		this.modalityIZList.refresh();
		
		
    }
	
	
	@Override
	public void cancelChange(){
		this.delegate.onCancelChange(this.versionableModality);
	}	
	

	public Modality getModality() {
		return modality;
	}

	public void setModality(Modality modality) {
		this.modality = modality;
	}

	@Override
	public DualListModel<Execution> getExecutions() {
		return executions;
	}

	@Override
	public DualListModel<VolumeType> getVolumes() {
		return volumes;
	}

	@Override
	public void setExecutions(DualListModel<Execution> executions) {
		this.executions = executions;
	}

	@Override
	public void setVolumes(DualListModel<VolumeType> volumes) {
		this.volumes = volumes;
	}

	@Override
	public List<TrainingType> getTrainingTypes() {
		return trainingTypes;
	}

	@Override
	public void setTrainingTypes(List<TrainingType> trainingTypes) {
		this.trainingTypes = trainingTypes;
	} 

	@Override
	public TrainingType getNewTrainingTypeValue() {
		return newTrainingTypeValue;
	}

	@Override
	public void setNewTrainingTypeValue(TrainingType newTrainingTypeValue) {
		this.newTrainingTypeValue = newTrainingTypeValue;
	}

	@Override
	public ModalityServiceInterface getModalityService() {
		return modalityService;
	}

	@Override
	public void setModalityService(ModalityServiceInterface modalityService) {
		this.modalityService = modalityService;
	}

	@Override
	public ModalityIZListCompInterface getModalityIZList() {
		return modalityIZList;
	}

	@Override
	public void setModalityIZList(ModalityIZListCompInterface modalityIZList) {
		this.modalityIZList = modalityIZList;
	}

	@Override
	public ExerciseTableCompInterface getExerciseTableComp() {
		return exerciseTableComp;
	}

	@Override
	public void setExerciseTableComp(ExerciseTableCompInterface exerciseTableComp) {
		this.exerciseTableComp = exerciseTableComp;
	}

	@Override
	public VersionableModality getVersionableModality() {
		return versionableModality;
	}

	@Override
	public void setVersionableModality(VersionableModality versionableModality) {
		this.versionableModality = versionableModality;
	}

	@Override
	public ModalityDetailDelegateInterface getDelegate() {
		return delegate;
	}

	@Override
	public void setDelegate(ModalityDetailDelegateInterface delegate) {
		this.delegate = delegate;
	}

	
	
}
